#pragma once

#include <vector>
#include <xtd/tree2d.h>

namespace outline {

/// The purpose of the class is to fetch node points from indexed_polyline class by
/// their index
template <typename T>
class extactor_by_index;

/// Object of this class is a closed or open polyline, that allows a user
/// to search the nearest node or nearest point on the polyline to the given one
template <typename T>
class indexed_polyline {
public:
	typedef size_t size_type;
	typedef T elem_type;
	typedef point<T> point_type;
public:
	/// creates open polyline
	template <typename I>
	indexed_polyline(I first, I last);
	/// creates closed polyline, with duplicate of ndup start nodes at the end and vice versa
	template <typename I>
	indexed_polyline(I first, I last, size_type ndup);
public:
	size_type size() const;
	bool is_closed() const;
	/// for closed polylines n is allowed to be in the range [-ndup, size()+ndup)
	point_type const & operator [] (int n) const;
	size_type nearest_node_index_to(point_type const & p) const;
	point_type const & nearest_node_to(point_type const & p) const;
	point_type nearest_point_to(point_type const & p) const;
private:
	typedef std::vector<point_type> node_vector;
	typedef xtd::tree2d<size_type, point_type, rect<elem_type>, extactor_by_index<T> > tree_type;
private:
	bool closed_;
	node_vector nodes_;
	size_type size_; ///< the number of not duplicate elements in nodes_
	point_type * begin_; ///< point on the first not duplicate element in nodes_
	tree_type tree_;
};

template <typename T>
class extactor_by_index {
public:
	typedef size_t size_type;
	typedef T elem_type;
	typedef point<T> point_type;
public:
	extactor_by_index(indexed_polyline<T> const & ip) :
		indexed_polyline_(ip) { }
	point_type const & operator () (size_type n) const
		{ return indexed_polyline_[n]; }
private:
	indexed_polyline<T> const & indexed_polyline_;
};

} //namespace outline
